package com.airlines.crewassignment.service.crew.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.airlines.common.DateTimeRangeUtil;
import com.airlines.common.ListSortUtil;
import com.airlines.crewassignment.domain.Crew;
import com.airlines.crewassignment.domain.CrewTask;
import com.airlines.crewassignment.domain.DateTimeRange;
import com.airlines.crewassignment.domain.crew.CrewRestDateTime;
import com.airlines.crewassignment.service.crew.CrewRestDateTimeService;
import com.airlines.crewassignment.service.crew.CrewTaskService;

/**
 * @author xxxx
 * @date 2018年5月2日 
 * @description
 */
@Service
public class CrewRestDateTimeServiceImpl implements CrewRestDateTimeService{
	@Autowired
	private CrewTaskService crewTaskService;

	@Override
	public List<CrewRestDateTime> listCrewRestDateTime(DateTimeRange dateTimeRange, List<Crew> crewList,String dutyCode,String workcode) {
		//1.查询机组人员某段时间内的任务列表
		List<CrewTask> taskList = crewTaskService.listCrewTask(dateTimeRange, dutyCode,null);
		
		//2.将任务转换为休息期
		//2.1按人分组
		Set<String> workcodeSet = new HashSet<>();
		for(CrewTask ct : taskList){
			workcodeSet.add(ct.getWorkcode());
		}
		
		List<CrewRestDateTime> allCrewRestDateTimeList = new ArrayList<>();
		
		for(String workcodeEvery : workcodeSet){
			//2.2组装每个人的任务列表
			List<CrewTask> taskListForEveryCrew = new ArrayList<>();
			for(CrewTask ct : taskList){
				if(StringUtils.equals(ct.getWorkcode(), workcodeEvery)){
					taskListForEveryCrew.add(ct);
				} 
			}
			
			//2.2每个人的任务列表，分割成M
			List<CrewRestDateTime> crewRestDateTimeList = this.listCrewRestDateTime(workcodeEvery, taskListForEveryCrew, dateTimeRange);
			allCrewRestDateTimeList.addAll(crewRestDateTimeList);			
		}
		
		
		//3如果说，某人没有任务，那么他的休息期就是整个时间
		List<Crew> hasNotTaskCrewList = new ArrayList<>();
		for(Crew crew : crewList){
			boolean flagHasNotTask = true;
			for(CrewRestDateTime crdt : allCrewRestDateTimeList){
				if(StringUtils.equals(crew.getWorkcode(), crdt.getWorkcode())){
					flagHasNotTask = false;
				}
			}
			
			if(flagHasNotTask){
				hasNotTaskCrewList.add(crew);
			}
		}
		
		for(Crew crew : hasNotTaskCrewList){
			CrewRestDateTime crdt = new CrewRestDateTime();
			crdt.setWorkcode(crew.getWorkcode());
			crdt.setRestDateTimeRange(dateTimeRange);
			allCrewRestDateTimeList.add(crdt);
		}
		ListSortUtil.sort(allCrewRestDateTimeList, true, "workcode","restDateTimeRange.end");
		return allCrewRestDateTimeList;
	}
	
	
	
	@Override
	public List<CrewRestDateTime> listCrewRestDateTime(String workcode,List<CrewTask> taskListForEveryCrew,DateTimeRange superRest){
		
		List<DateTimeRange> restDateTimeRangeAll = new ArrayList<>();
		//1.将每个任务插入总休息时间段后，获得所有的休息片段
		for(CrewTask ct : taskListForEveryCrew){ 
			DateTimeRange task = new DateTimeRange(ct.getStart(),ct.getEnd());
			List<DateTimeRange> restTemp = this.restDateTimeRangeBuild(superRest, task);
			restDateTimeRangeAll.addAll(restTemp);
		}
		return this.listCrewRestDateTime(workcode, restDateTimeRangeAll);
	}

	@Override
	public List<CrewRestDateTime> listCrewRestDateTime(String workcode ,List<DateTimeRange> restDateTimeRangeAll){
		Set<DateTimeRange> restUnionDateTimeRangeSet = new HashSet<>();
		for(DateTimeRange rest : restDateTimeRangeAll){
			DateTimeRange restTemp = rest;
			for(DateTimeRange restOther : restDateTimeRangeAll){
				restTemp = getUnionDateTimeRange(restTemp,restOther);
			}
			restUnionDateTimeRangeSet.add(restTemp);
		}
		//3.获取到了所有休息期片段后，将相连的休息片段连起来，化零为整
		//3.1获取素有的时间点
		List<Date> dateList = new ArrayList<Date>();
		for(DateTimeRange dtr : restUnionDateTimeRangeSet){
			dateList.add(dtr.getStart());
			dateList.add(dtr.getEnd());
		}
		
		//3.2去除相邻的时间节点
		List<Date> dateListNotExistsJoinPoint = new ArrayList<Date>();
		for(Date date : dateList){
			int count = 0;
			for(Date dateOther : dateList){
				if(date.equals(dateOther)){
					count ++;
				}
			}
			if(count<=1){
				dateListNotExistsJoinPoint.add(date);
			}
		}
		
		//3.3去除相邻节点后,剩余数量必定为偶数，每2个组成一对，则为最终合并的休息期
		Collections.sort(dateListNotExistsJoinPoint);
		List<CrewRestDateTime> crewRestDateTimeList = new ArrayList<>();
		for(int i = 0 ; i+1 < dateListNotExistsJoinPoint.size() ; i=i+2){
			DateTimeRange restDateTimeRange = new DateTimeRange(dateListNotExistsJoinPoint.get(i),dateListNotExistsJoinPoint.get(i+1));
			CrewRestDateTime crewRestDateTime = new CrewRestDateTime();
			crewRestDateTime.setWorkcode(workcode);
			crewRestDateTime.setRestDateTimeRange(restDateTimeRange);
			crewRestDateTimeList.add(crewRestDateTime);
		}
		
		return crewRestDateTimeList;
	}
 
	/**
	 * 将一个休息期时间段，插入一个任务期，获取分割后的休息期
	 * @param rest
	 * @param task
	 * @return
	 */
	private List<DateTimeRange> restDateTimeRangeBuild(DateTimeRange rest,DateTimeRange task){
		List<DateTimeRange> allRestList = new ArrayList<>();
        if(DateTimeRangeUtil.isIntersection(rest,task)){
        	 //将2个时间段的4个时间点排序
        	 List<Date> dateList = new ArrayList<>();
        	 dateList.add(rest.getStart());
        	 dateList.add(rest.getEnd());
        	 dateList.add(task.getStart());
        	 dateList.add(task.getEnd());
             Collections.sort(dateList);
             
             //任务期插入休息期，则必定得到3个时间段
             for(int i = 0;i<=2;i++){
            	 DateTimeRange restTemp = new DateTimeRange(dateList.get(i),dateList.get(i+1));
            	 //如果每个时间段与任务不相交，则必定为休息期
            	 if(!DateTimeRangeUtil.isIntersection(restTemp,task)){
            		 allRestList.add(restTemp);
            	 }
             }
        }else{
        	//如果没有交集，则返回原休息期时间段
        	allRestList.add(rest);
        }
    	return allRestList;
	}
	
	

	
	/**
	 * 获取两个时间段的交集,如果没有交集，则返回 dt1
	 * @param dt1
	 * @param dt2
	 * @return
	 */
	private DateTimeRange getUnionDateTimeRange(DateTimeRange dt1, DateTimeRange dt2){
		if(DateTimeRangeUtil.isIntersection(dt1,dt2)){
			 List<Date> dateList = new ArrayList<>();
        	 dateList.add(dt1.getStart());
        	 dateList.add(dt1.getEnd());
        	 dateList.add(dt2.getStart());
        	 dateList.add(dt2.getEnd());
             Collections.sort(dateList);
             
             return new DateTimeRange(dateList.get(1),dateList.get(2));
		}
		return dt1;
	}
	
}
